﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Windows.Forms;
using System.Text.RegularExpressions;
using FRW.Common.Extensions;
using FRW.Common;
using FRW.Common.Configuration;

namespace Money.Plugins.Import
{
    // TODO Need to tidy up imported files if the import is cancelled, at present they appear in the imported directory even if import is cancelled.
    public class ImportTransactions : IPluginDataAccess
    {
        protected string ImportFolder;
        protected string LogFolder;
        protected IDataSet _dataAccessInterface;

        protected List<ImportFile> _importFiles;

        public ImportTransactions(string importHandlerName)
        {
            PathManager.Instance.DataFolderUpdated += DataFolderUpdated;
            PathManager.Instance.ApplicationFolderUpdated += ApplicationFolderUpdated;

            CheckDataPaths();
            CheckApplicationPaths();
        }

        public bool AddFile(ImportFile importFile)
        {
            bool status = true;

            if (_importFiles == null)
            {
                _importFiles = new List<ImportFile>();
            }

            importFile.IsSkipped = false;
            _importFiles.Add(importFile);

            return status;
        }

        private void DataFolderUpdated(object sender, EventArgs ev)
        {
            CheckDataPaths();
        }

        private void ApplicationFolderUpdated(object sender, EventArgs ev)
        {
            CheckApplicationPaths();
        }

        private void CheckDataPaths()
        {
            ImportFolder = PathManager.Instance.DataFolder + @"\Imported\";

            // check if the a folder exists for outputting Import information
            DirectoryInfo di = new DirectoryInfo(ImportFolder);
            if (di.Exists == false)
            {
                di.Create();
            }
        }

        private void CheckApplicationPaths()
        {
            LogFolder = PathManager.Instance.ApplicationFolder + @"\Log\";

            // check if the a folder exists for outputting Import information
            DirectoryInfo di = new DirectoryInfo(LogFolder);
            if (di.Exists == false)
            {
                di.Create();
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public virtual void ImportCancelled()
        {
            foreach (ImportFile importFile in _importFiles)
            {
                if (importFile.IsSkipped == false)
                {
                    if (File.Exists(ImportedFileName(importFile.FileName)))
                    {
                        File.Delete(ImportedFileName(importFile.FileName));
                    }
                }
            }
        }

        public virtual void ResetHandler()
        {
            _importFiles.Clear();
        }

        public virtual void Log(string logText)
        {
            using (FileStream logFile = new FileStream(LogFileName(), FileMode.Append, FileAccess.Write))
            {
                using (StreamWriter log = new StreamWriter(logFile))
                {
                    logText = "[" + DateTime.Now.ToString() + "] " + logText;
                    log.WriteLine(logText);
                }
            }
        }

        public virtual void ResetTransaction(Transaction current)
        {
        }

        // TODO this should possibly be in a central location?
        protected string NameUpdate(string description, IEnumerable<DescriptionMatch> names)
        {
            var sortedList = from descriptionMatch in names 
                             orderby descriptionMatch.Priority descending 
                             select descriptionMatch;

            foreach (DescriptionMatch name in sortedList.ToList())
            {
                if (Regex.IsMatch(description, name.RegularExpression, RegexOptions.IgnoreCase))
                {
                    if (!string.IsNullOrWhiteSpace(name.Description))
                    {
                        description = name.Description;
                    }

                    if (name.Terminate)
                    {
                        break;
                    }
                }
            }

            return description;
        }

        protected virtual string ImportedFileName(string file)
        {
            FileInfo saveFile = new FileInfo(file);
            string fileName = ImportFolder + GetType().ToString() + "." + saveFile.Name + ".xml";

            return (fileName);
        }

        protected void SaveImportedRecords(object obj, string file)
        {
            Serialize.ToXMLFile(obj, ImportedFileName(file));
        }

        protected virtual string LogFileName()
        {
            string fileName = LogFolder + "Import.Log";

            return (fileName);
        }

        public virtual string GetOriginalTransaction(long transactionNumber)
        {
            return "";
        }

        /// <summary>
        /// Check if the specified file has been imported before
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns>true - if the file has been imported before</returns>
        protected bool IsAlreadyImported(string fileName)
        {
            FileInfo file;

            file = new FileInfo(ImportedFileName(fileName));

            // check if the file exists, if it does then we have already imported this file and we should display a warning
            if (file.Exists)
            {
                return true;
            }

            return false;
        }

        void IPluginDataAccess.SetDataAccessInterface(IDataSet dataAccessInterface)
        {
            _dataAccessInterface = dataAccessInterface;
        }

        /// <summary>
        /// Obtain the list of all files that have previously been imported
        /// </summary>
        /// <returns>List of files that have been imported previously</returns>
        protected IEnumerable<string> GetImportedFileList()
        {
            foreach (string file in Directory.GetFiles(ImportFolder, GetType().ToString() + "*.*"))
            {
                yield return file;
            }
        }
    }
}
